-- Register Selector Architecture
-- Chang Lan, <changlan9@gmail.com>
-- 11/9/2011

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

architecture behave of regselect is

begin
    process(op, rx, ry, rz)
        constant EMPTY_ADDRESS : std_ulogic_vector(3 downto 0) := "1111";
    begin
        case op is
            when OP_ADDIU =>
                reg_r1 <= '0' & rx;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= '0' & rx;
				when OP_ADDIU3 =>
                reg_r1 <= '0' & rx;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= '0' & ry;
            when OP_ADDSP3 =>
                reg_r1 <= RegAddr_SP;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= '0' & rx;
            when OP_ADDSP =>
                reg_r1 <= RegAddr_SP;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= RegAddr_SP;
            when OP_ADDU | OP_SUBU =>
                reg_r1 <= '0' & rx;
                reg_r2 <= '0' & ry;
                reg_w  <= '0' & rz;
            when OP_AND | OP_OR | OP_XOR =>
                reg_r1 <= '0' & rx;
                reg_r2 <= '0' & ry;
                reg_w  <= '0' & rx;
            when OP_B =>
                reg_r1 <= EMPTY_ADDRESS;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= EMPTY_ADDRESS;
			when OP_BEQZ | OP_BNEZ =>
                reg_r1 <= '0' & rx;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= EMPTY_ADDRESS;
			when OP_BTEQZ | OP_BTNEZ =>
                reg_r1 <= RegAddr_T;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= EMPTY_ADDRESS;
            when OP_CMP | OP_SLT | OP_SLTU =>
                reg_r1 <= '0' & rx;
                reg_r2 <= '0' & ry;
                reg_w  <= RegAddr_T;
            when OP_CMPI | OP_SLTI | OP_SLTUI =>
                reg_r1 <= '0' & rx;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= RegAddr_T;
            when OP_JALR =>
                reg_r1 <= '0' & rx;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= RegAddr_RA;
            when OP_JR =>
                reg_r1 <= '0' & rx;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= EMPTY_ADDRESS;
            when OP_JRRA =>
                reg_r1 <= RegAddr_RA;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= EMPTY_ADDRESS;
            when OP_LI =>
                reg_r1 <= EMPTY_ADDRESS;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= '0' & rx;
            when OP_LW =>
                reg_r1 <= '0' & rx;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= '0' & ry;
            when OP_LW_SP =>
                reg_r1 <= RegAddr_SP;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= '0' & rx;
            when OP_MFIH =>
                reg_r1 <= RegAddr_IH;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= '0' & rx;
            when OP_MFPC =>
                reg_r1 <= EMPTY_ADDRESS;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= '0' & rx;
            when OP_MOVE =>
                reg_r1 <= '0' & ry;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= '0' & rx;
            when OP_MTIH =>
                reg_r1 <= '0' & rx;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= RegAddr_IH;
            when OP_MTSP =>
                reg_r1 <= '0' & ry;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= RegAddr_SP;
            when OP_NEG | OP_NOT | OP_SLL | OP_SRA | OP_SRL =>
                reg_r1 <= '0' & ry;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= '0' & rx;
            when OP_SLLV =>
                reg_r1 <= '0' & rx;
                reg_r2 <= '0' & ry;
                reg_w  <= '0' & ry;
			   when OP_SRAV | OP_SRLV =>
                reg_r1 <= '0' & ry;
                reg_r2 <= '0' & rx;
                reg_w  <= '0' & ry;
            when OP_SW =>
                reg_r1 <= '0' & rx;
                reg_r2 <= '0' & ry;
                reg_w  <= EMPTY_ADDRESS;
            when OP_SW_RS =>
                reg_r1 <= RegAddr_SP;
                reg_r2 <= RegAddr_RA;
                reg_w  <= EMPTY_ADDRESS;
            when OP_SW_SP =>
                reg_r1 <= RegAddr_SP;
                reg_r2 <= '0' & rx;
                reg_w  <= EMPTY_ADDRESS; 
			when OP_INT1 =>
				reg_r1 <= RegAddr_SP;
				reg_r2 <= EMPTY_ADDRESS;
				reg_w  <= EMPTY_ADDRESS;
			when OP_INT2 =>
				reg_r1 <= RegAddr_SP;
				reg_r2 <= EMPTY_ADDRESS;
				reg_w  <= RegAddr_SP;
			when OP_INT3 =>
				reg_r1 <= RegAddr_IH;
				reg_r2 <= EMPTY_ADDRESS;
				reg_w  <= RegAddr_IH;
            when others => 
                reg_r1 <= EMPTY_ADDRESS;
                reg_r2 <= EMPTY_ADDRESS;
                reg_w  <= EMPTY_ADDRESS;
        end case;
    end process;
end behave;

